home *** CD-ROM | disk | FTP | other *** search
- /*
- ** dispatch.c - dispatcher for XPK DataType class
- ** Copyright © 1995 Michael Letowski
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/dosasl.h>
- #include <intuition/classes.h>
- #include <datatypes/datatypesclass.h>
- #include <datatypes/datatypes.h>
- #include <libraries/xpk.h>
- #include <utility/tagitem.h>
- #include <support/types.h>
- #include <support/dos.h>
-
- #include <string.h>
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/datatypes.h>
- #include <proto/intuition.h>
- #include <proto/utility.h>
- #include <clib/support_protos.h>
-
- #include "classbase.h"
- #include "dispatch.h"
-
-
- /****** xpk.datatype/xpk.datatype *******************************************
- *
- * NAME
- * xpk.datatype -- data type for XPK and PowerPacker compressed files.
- *
- * FUNCTION
- * The xpk data type is used to decompress XPK and PowerPacker
- * compressed files. Decompressed files are then placed in "T:" logical
- * directory and passed again to DataTypes system via NewDTObject().
- * DataTypes system is then free to handle them (it will usually show
- * contents of a decompressed file).
- *
- * METHODS
- * OM_NEW -- Decompress source file, place it in "T:" directory and call
- * OM_NEW method on that file.
- *
- * OM_DISPOSE -- Delete the object and all associated temporary files.
- *
- * NOTES
- * Since the data type just calls OM_NEW method on a decompressed file
- * it will work for files which were compressed several times (eg. DLTA
- * encoded and SHRI compressed).
- *
- * BUGS
- * Will not work for AmigaGuide® compressed files (due to a bug in
- * amigaguide.datatype, I suspect).
- * Can not handle encrypted files.
- *
- * SEE ALSO
- * amigaguide.datatype, xpkmaster.library, datatypes.library.
- *
- *****************************************************************************
- *
- */
-
-
- /*
- ** Private structures
- */
- struct XPKData
- {
- Object *xd_Object;
- STRPTR xd_Name;
- }; /* XPKData */
-
-
- /*
- ** Private prototypes
- */
- STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
- STATIC Object *NewXPK(Class *cl, Object *o, Msg msg);
- STATIC Object *DisposeXPK(Class *cl, Object *o, Msg msg);
- STATIC Object *DefaultXPK(Class *cl, Object *o, Msg msg);
- STATIC STRPTR CreateTempFile(struct ClassBase *cb, STRPTR name);
- STATIC VOID DeleteTempFile(struct ClassBase *cb, STRPTR name);
- STATIC LONG XPK2DOS(struct ClassBase *cb, LONG xpkError);
-
-
- /*
- ** DataTypes stubs
- */
- STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
- STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
-
-
- /*
- ** xpk.h kludge
- */
- #pragma tagcall XpkBase XpkUnpackTags 30 801
-
-
- /*
- ** Public functions
- */
- Class *InitClass(struct ClassBase *cb)
- {
- Class *CL;
-
- /* Create our class (an instance of XPKData) */
- if(CL=MakeClass(DATATYPENAME,SUPERCLASSNAME,NULL,sizeof(struct XPKData),0))
- {
- CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
- CL->cl_UserData=(ULONG)cb;
- AddClass(CL);
- }
- return(CL);
- } /* InitClass */
-
-
- /*
- ** Level 1 private functions
- */
- STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
- {
- Object *Obj;
-
- switch(msg->MethodID)
- {
- case OM_NEW: Obj=NewXPK(cl,o,msg); break;
- case OM_DISPOSE: Obj=DisposeXPK(cl,o,msg); break;
- default: Obj=DefaultXPK(cl,o,msg); break;
- }
- return(Obj);
- } /* Dispatch */
-
-
- /*
- ** Level 2 private functions
- */
- STATIC Object *NewXPK(Class *cl, Object *o, Msg msg)
- {
- STATIC CONST struct TagItem UnpackTags[]=
- {
- {XPK_PassThru, TRUE},
- {TAG_DONE, 0}
- }; /* UnpackTags */
- STATIC CONST Tag FilterTags[]=
- {
- DTA_SourceType,DTA_DataType,DTA_Name,DTA_Handle,TAG_DONE
- }; /* FilterTags */
-
- struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
- struct TagItem *Clone,*Tag;
- struct TagItem *Attrs=((struct opSet *)msg)->ops_AttrList;
- Object *NewObj=NULL;
- struct XPKData *XD;
- STRPTR Name,RealName;
- BPTR Lock,Lock2,Handle;
- LONG Err,RC=0;
-
- try(Clone=CloneTagItems(Attrs), NO_CLONE);
-
- /* Get name and object lock */
- RealName= (STRPTR)GetTagData(DTA_Name,NULL,Clone);
- Lock= (BPTR)GetTagData(DTA_Handle,NULL,Clone);
- try(RealName && Lock, NO_LOCK);
-
- /* Remove unnecessary attributes */
- FilterTagItems(Clone,FilterTags,TAGFILTER_NOT);
-
- if(Name=CreateTempFile(cb,RealName)) /* Create temporary file name */
- {
- Err=XPKERR_IOERRIN; /* No success yet */
- if(Lock2=DupLock(Lock)) /* Get duplicate of lock */
- if(Handle=OpenFromLock(Lock2)) /* Open from that lock */
- { /* Could open - Lock2 is invalid */
- /* Do unpacking */
- Err=XpkUnpackTags(XPK_InFH, Handle,
- XPK_OutName, Name,
- TAG_MORE, UnpackTags);
- Close(Handle); /* Close file */
- }
- else /* Could not open */
- UnLock(Lock2); /* Unlock file */
-
- if(Err==XPKERR_OK || Err==XPKERR_NOTPACKED) /* Error? */
- /* Create new object */
- if(NewObj=(Object *)DoSuperMethodA(cl,o,msg))
- {
- XD=INST_DATA(cl,NewObj);
- if(XD->xd_Object=NewDTObjectA(Name,Clone))
- {
- SetAttrs(NewObj,DTA_ObjName,RealName,TAG_DONE);
- XD->xd_Name=Name;
- }
- else /* Could not create object */
- {
- RC=IoErr(); /* Get DOS error code */
- CoerceMethod(cl,NewObj,OM_DISPOSE); /* Destroy object (super class) */
- NewObj=NULL; /* Mark this fact */
- }
- }
- else /* Error creating object */
- RC=IoErr(); /* Get DOS error code */
- else /* Error unpacking */
- RC=XPK2DOS(cb,Err); /* Get DOS error code */
- }
- else /* Error creating temp file */
- RC=IoErr(); /* Get DOS error code */
-
- unless(NewObj) /* New object not created */
- DeleteTempFile(cb,Name); /* Delete temporary file */
-
- /* Exceptions */
- SetIoErr(RC); /* Set error code */
- catch(NO_LOCK, );
- catch(NO_CLONE, FreeTagItems(Clone));
- return(NewObj);
- } /* NewXPK */
-
- STATIC Object *DisposeXPK(Class *cl, Object *o, Msg msg)
- {
- struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
- struct XPKData *XD=INST_DATA(cl,o);
-
- if(XD->xd_Object) DisposeDTObject(XD->xd_Object);
- if(XD->xd_Name) DeleteTempFile(cb,XD->xd_Name);
- return((Object *)DoSuperMethodA(cl,o,msg));
- } /* DisposeXPK */
-
- STATIC Object *DefaultXPK(Class *cl, Object *o, Msg msg)
- {
- struct XPKData *XD=INST_DATA(cl,o);
-
- return((Object *)DoMethodA(XD->xd_Object,msg));
- } /* DefaultXPK */
-
-
- /*
- ** Level 3 private functions
- */
- STATIC STRPTR CreateTempFile(struct ClassBase *cb, STRPTR name)
- {
- STRPTR Name,RealName=FilePart(name);
- ULONG Len;
- BPTR DirLock;
-
- Len=strlen(RealName)+24;
- if(Name=AllocVec(Len,MEMF_PUBLIC)) /* Allocate space for name */
- { /* Space allocated */
- SPrintf(Name,"T:XPKDT-%08lx-T%04ld",ThisProcessS,cb->cb_UniqueCnt++);
- if(DirLock=CreateDir(Name)) /* Try to create directory */
- { /* Could create directory */
- AddPart(Name,RealName,Len); /* Append file name */
- UnLock(DirLock); /* Free lock */
- }
- else /* Dir not created */
- { /* Create unique file name */
- strcat(Name,"-"); /* Append dash */
- strcat(Name,RealName); /* Append file name */
- }
- }
- return(Name);
- } /* CreateTempFile */
-
- STATIC VOID DeleteTempFile(struct ClassBase *cb, STRPTR name)
- {
- STRPTR Sep;
-
- if(name) /* Name valid */
- {
- Sep=PathPart(name); /* Find path/file separator */
- DeleteFile(name); /* Delete file */
- if(Sep!=FilePart(name)) /* Dir component present */
- {
- *Sep='\0'; /* Null terminate string */
- DeleteFile(name); /* Delete directory */
- }
- FreeVec(name); /* Free space */
- }
- } /* DeleteTempFile */
-
- STATIC LONG XPK2DOS(struct ClassBase *cb, LONG xpkErr)
- {
- LONG DOSErr=ThisProcessS->pr_Result2;
-
- unless(DOSErr) /* Error not set */
- switch(xpkErr)
- {
- case XPKERR_NOFUNC: DOSErr=ERROR_NOT_IMPLEMENTED; break;
- case XPKERR_NOFILES: DOSErr=ERROR_NOT_IMPLEMENTED; break;
- case XPKERR_IOERRIN: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_IOERROUT: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_CHECKSUM: DOSErr=DTERROR_INVALID_DATA; break;
- case XPKERR_VERSION: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_NOMEM: DOSErr=ERROR_NO_FREE_STORE; break;
- case XPKERR_LIBINUSE: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_WRONGFORM: DOSErr=DTERROR_UNKNOWN_COMPRESSION; break;
- case XPKERR_SMALLBUF: DOSErr=ERROR_BUFFER_OVERFLOW; break;
- case XPKERR_LARGEBUF: DOSErr=ERROR_BUFFER_OVERFLOW; break;
- case XPKERR_WRONGMODE: DOSErr=DTERROR_UNKNOWN_COMPRESSION; break;
- case XPKERR_NEEDPASSWD: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_CORRUPTPKD: DOSErr=DTERROR_INVALID_DATA; break;
- case XPKERR_MISSINGLIB: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_BADPARAMS: DOSErr=ERROR_TOO_MANY_ARGS; break;
- case XPKERR_EXPANSION: DOSErr=ERROR_BUFFER_OVERFLOW; break;
- case XPKERR_NOMETHOD: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_ABORTED: DOSErr=ERROR_BREAK; break;
- case XPKERR_TRUNCATED: DOSErr=DTERROR_NOT_ENOUGH_DATA; break;
- case XPKERR_WRONGCPU: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_PACKED: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_NOTPACKED: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_FILEEXISTS: DOSErr=ERROR_OBJECT_EXISTS; break;
- case XPKERR_OLDMASTLIB: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_OLDSUBLIB: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_NOCRYPT: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_NOINFO: DOSErr=ERROR_INVALID_RESIDENT_LIBRARY; break;
- case XPKERR_LOSSY: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- case XPKERR_NOHARDWARE: DOSErr=ERROR_NOT_IMPLEMENTED; break;
- case XPKERR_BADHARDWARE: DOSErr=ERROR_NOT_IMPLEMENTED; break;
- case XPKERR_WRONGPW: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- default: DOSErr=ERROR_OBJECT_WRONG_TYPE; break;
- }
- return(DOSErr);
- } /* XPK2DOS */
-
-
- /*
- ** DataTypes stubs
- */
- STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
- {
- return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
- } /* LocSetDTAttrs */
-
- STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
- {
- return(GetDTAttrsA(o,(struct TagItem *)&data));
- } /* LocGetDTAttrs */
-